#include "async_redis.hpp"
#include "actor.h"

std::string rand_str(int len) {
    std::string str;
    int i = 0;
    for (i = 0; i < len; ++i) {
	str += 'A' + rand()%26;
    }
    str[++i] = '\0';
    return str;
}
int main(int argc, char * argv[])
{
    const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1";
    int port = (argc > 2) ? atoi(argv[2]) : 6379;
    std::string  pass = (argc > 3) ? argv[3] : "";
    int count = (argc > 4) ? atoi(argv[4]): 1; 
    int size = (argc > 5) ? atoi(argv[5]): 1; 
    int thrds = (argc > 6) ? atoi(argv[6]): 8; 
    int action = (argc > 7) ? atoi(argv[7]): 1; 
    if (strcmp(hostname,"-h") == 0)
    {
	printf("usage : hostname port pass  count size  threads \n"); 
	return 0; 
    }

    if (pass == "false")
    {
	pass = ""; 
    }

    DLog("test %s:%d   size %d thrds %d ",hostname,port,size,thrds); 
    bool isRunning  = true; 
    AsyncRedis asyncRedis; 
    asyncRedis.start(hostname,port,pass,thrds ); 
    int batch = 10;

    uint64_t result_count = 0; 
    bool isConnected = false; 
    std::vector<double > duration_list; 
    double start_time = GetMilliSeconds(); 

    int total_count = thrds* batch*count * 10000-1; 
    int curConn  = 0 ; 
    while(isRunning )
    {

	asyncRedis.process_result([&](RedisResult * pRst ){

		switch(pRst->type)
		{
		case EVT_CONNECT:
		case EVT_AUTH:
		{
		    curConn ++ ; 
		    //printf("current count %d\n",curConn); 
		    if (curConn == thrds ) 
		    {
			printf("all connected \n"); 
			isConnected = true; 
		    }
		    //printf("process redis connect event \n"); 
		}
		break; 

		case EVT_RESULT:
		{
		    duration_list.push_back(pRst->get_duration());
		    //DLog("process redis result %llu\n",result_count); 
		    result_count ++; 

		    if (result_count >= total_count)
		    {
			isRunning = false; 
		    }
		    //printf("process redis result :%s\n",pRst->command.c_str()); 
		}

		break; 

		}

	}); 

	if (isConnected && batch-- > 0 )
	{
	    char szCmd[256] = {0}; 
	    char szUser[32]= {0} ; 
	    std::string str = rand_str(1024*size);
	    Actor actor;
	    actor.props = str+"props";
	    actor.props2 = str+"props2";

	    if (action == 1)
	    {
		//DLog("starting execute command "); 
		for(int i = 0;i < thrds * count *10000; i++)
		{
		    sprintf(szUser,"key%d",i); 
		    asyncRedis.execute(i, hmset(szUser, actor)); 
		}
	    }
	    else 
	    {
		for(int i = 0;i < thrds * count *10000; i++)
		{
		    sprintf(szUser,"key%d",i); 
		    asyncRedis.execute(i, hmget(szUser)); 
		}
	    }

	    std::this_thread::sleep_for(std::chrono::microseconds(1));
	}
	else 
	{

	    std::this_thread::sleep_for(std::chrono::seconds(1));
	}
    }
    asyncRedis.stop(); 

    double total = 0.0; 
    for(auto dura: duration_list)
    {
	total += dura; 
    }

    std::cout << "average duration is " << total / duration_list.size() << std::endl; 


    printf("stop client ... escaped time %lf \n", GetMilliSeconds() -start_time ); 
    //char ch = getchar(); 
    //
    //    while(ch != 'q')
    //    {
    //
    //    }


    return 0; 
}
